/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.veditor.view.ev;

import offset.nodes.client.veditor.model.ev.DataElementView;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.Node;
import javax.swing.JOptionPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import offset.nodes.client.chooser.model.GetNodeByUuid;
import offset.nodes.client.chooser.view.QueryResultChooserDialog;
import offset.nodes.client.model.ServerModel;
import offset.nodes.client.virtual.model.jcr.NodeReader;
import offset.nodes.client.virtual.model.jcr.QName;
import offset.nodes.client.view.SimpleDialog;
import offset.nodes.client.editor.Editor;
import offset.nodes.client.veditor.model.DataModel;

/**
 *
 * @author Walter Lütgenau
 */
public class NodeFromTypeChooser implements DataElementView {

    DataElementViewContext context = null;

    public int getResult() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void setContext(DataElementViewContext context) {
        try {
            this.context = context;
            Map properties = context.getVirtualBlock().getModel().getProperties();
            String serverUrl = (String) properties.get(Editor.PROP_UPLOAD_TO);
            ServerModel server = new ServerModel(new URL(serverUrl));

            Element schema = getSchemaElement(context.getElement());
            String nodeType = getNodeTypePrefixName(schema);

            QueryResultChooserDialog dialog = new QueryResultChooserDialog(new javax.swing.JFrame(),
                    true, server, "//element(*," + nodeType + ")");
            dialog.setVisible(true);

            if (dialog.getResult() == SimpleDialog.OK) {
                String uuid = dialog.getUuid();
                if (uuid == null) {
                    JOptionPane messageDialog = new JOptionPane();
                    messageDialog.showMessageDialog(null, ResourceBundle.getBundle("offset/nodes/client/editor/view/resources/EditorBundle").getString("selectNode.invalidNode"));

                    return;
                }
                Node node = getNode(server, uuid);
                updateSchemaTree(schema, node, uuid);
            }
        } catch (Exception ex) {
            Logger.getLogger(NodeFromTypeChooser.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    protected void updateSchemaTree(Element schemaElement, Node node, String uuid) throws Exception {
        DataModel model = context.getVirtualBlock().getModel();

        StringBuffer buf = new StringBuffer();

        SimpleAttributeSet atts = new SimpleAttributeSet(schemaElement.getAttributes());
        atts.addAttribute(DataModel.ATTRIBUTE_NAME_PRIMARY_REFERENCE, uuid);
        buf.append(model.getStartTag(atts));
        for (int i = 0; i < schemaElement.getElementCount(); i++) {
            buf.append(substituteContent(schemaElement.getElement(i), node, model.getData(schemaElement)));
        }
        buf.append(model.getEndTag(atts));
        
        model.setOuterHTML(schemaElement, buf.toString());
    }

    protected String substituteContent(Element e, Node node, String nodeName) throws Exception {
        StringBuffer buf = new StringBuffer();
        DataModel model = context.getVirtualBlock().getModel();

        e = model.getHtmlElement(e);
        AttributeSet atts = e.getAttributes();

        buf.append(model.getStartTag(atts));

        if (model.hasData(e)) { // ordinary element with data
            String data = model.getDataPath(e);

            if (!data.startsWith(nodeName)) // a different nodeType
                return model.getOuterHTML(e);

            data = data.substring(nodeName.length() + 1);
            if (data.startsWith("@")) { // a property. Substitute the property value
                String propertyValue;
                if (data.substring(1).equals(QName.NAME_PROPERTY.getLocalName()))
                    propertyValue = node.getName();
                else
                    propertyValue = node.getProperty(data.substring(1)).getString();

                buf.append(propertyValue);
                buf.append(model.getEndTag(atts));
                return buf.toString();
            } else { // substitute the subnode
                int end = data.indexOf("/");
                if (end >= 0)
                    data = data.substring(0, end);
                node = node.getNode(data);
                if (model.isLeaf(e)) {
                    throw new Exception("hurray");
                }
            }
        }

        if (model.isLeaf(e)) {
            buf.append(model.getContent(e));
            buf.append(model.getEndTag(atts));

            return buf.toString();
        }

        for (int i = 0; i < e.getElementCount(); i++) {
            buf.append(substituteContent(e.getElement(i), node, nodeName));
        }

        buf.append(model.getEndTag(atts));
        return buf.toString();
    }

    protected Node getNode(ServerModel server, String uuid) throws Exception {
        // Get properties of the selected node
        GetNodeByUuid.Request request = new GetNodeByUuid.Request();
        request.setUuid(uuid);
        GetNodeByUuid.Response response = (GetNodeByUuid.Response) server.sendRequest(request);
        NodeReader reader = new NodeReader();
        Node node = reader.read(new ByteArrayInputStream(response.getNode().getBytes()));

        return node;
    }

    protected Element getSchemaElement(Element e) {
        while (e != null) {
            if (e.getAttributes().isDefined(DataModel.ATTRIBUTE_NAME_SCHEMA))
                return e;
            e = e.getParentElement();
        }

        return e;
    }

    protected String getNodeTypePrefixName(Element schemaElement) {
        return (String) schemaElement.getAttributes().getAttribute(DataModel.ATTRIBUTE_NAME_SCHEMA);
    }
}
